{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>0</th>\n",
       "      <th>1</th>\n",
       "      <th>2</th>\n",
       "      <th>3</th>\n",
       "      <th>4</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>5.1</td>\n",
       "      <td>3.5</td>\n",
       "      <td>1.4</td>\n",
       "      <td>0.2</td>\n",
       "      <td>Iris-setosa</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>4.9</td>\n",
       "      <td>3.0</td>\n",
       "      <td>1.4</td>\n",
       "      <td>0.2</td>\n",
       "      <td>Iris-setosa</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>4.7</td>\n",
       "      <td>3.2</td>\n",
       "      <td>1.3</td>\n",
       "      <td>0.2</td>\n",
       "      <td>Iris-setosa</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>4.6</td>\n",
       "      <td>3.1</td>\n",
       "      <td>1.5</td>\n",
       "      <td>0.2</td>\n",
       "      <td>Iris-setosa</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5.0</td>\n",
       "      <td>3.6</td>\n",
       "      <td>1.4</td>\n",
       "      <td>0.2</td>\n",
       "      <td>Iris-setosa</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     0    1    2    3            4\n",
       "0  5.1  3.5  1.4  0.2  Iris-setosa\n",
       "1  4.9  3.0  1.4  0.2  Iris-setosa\n",
       "2  4.7  3.2  1.3  0.2  Iris-setosa\n",
       "3  4.6  3.1  1.5  0.2  Iris-setosa\n",
       "4  5.0  3.6  1.4  0.2  Iris-setosa"
      ]
     },
     "execution_count": 84,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "iris = pd.read_table('iris.txt',header=None,sep=',')\n",
    "iris.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {},
   "outputs": [],
   "source": [
    "'''\n",
    "函数功能：欧氏距离计算公式\n",
    "'''\n",
    "def disEclud(vecA,vecB):\n",
    "   return np.sum( np.power(vecA-vecB,2),axis=1)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {},
   "outputs": [],
   "source": [
    "def randCent(df, k):\n",
    "    n = df.shape[1]\n",
    "    #特征值列\n",
    "    data_min =df.iloc[:,:n-1].min() \n",
    "    data_max =df.iloc[:,:n-1].max()\n",
    "    #随机制定k个质心\n",
    "    return np.random.uniform(data_min,data_max,(k,n-1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[4.32010663, 3.97938518, 1.21929667, 2.4779764 ],\n",
       "       [5.12210925, 2.64532825, 6.04247241, 1.03488284],\n",
       "       [4.91142836, 3.78668985, 2.49865942, 1.11539495]])"
      ]
     },
     "execution_count": 87,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "randCent(iris,3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "创建k个点作为初始质心(通常是随机选择)\n",
    "当任意一个点的簇分配结果发生改变时:\n",
    "对数据集中的每个点:\n",
    "对每个质心:\n",
    "计算质心 与数据点之间的距离\n",
    "将数据点分配到据其最近的簇\n",
    "对每个簇，计算簇中所有点的均值并将均值作为新的质心\n",
    "直到簇不再发生变化或者达到最大迭代次数\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "metadata": {},
   "outputs": [],
   "source": [
    "'''\n",
    "函数功能：\n",
    "    k举止聚类\n",
    "输入：\n",
    "    df:数据集\n",
    "    k:聚类簇的个数\n",
    "    distMet:距离计算公式\n",
    "    createCent：质心初始化函数\n",
    "'''\n",
    "\n",
    "def kmeans(df,k,disMet=disEclud,creatCent = randCent):\n",
    "    m,n = df.shape\n",
    "    #初始化质心\n",
    "    centroids = creatCent(df,k)\n",
    "    #序列数据存储\n",
    "    clusterAssment = np.zeros((m,3))\n",
    "    clusterAssment[:,0] = np.inf\n",
    "    clusterAssment[:,1:3] = -1\n",
    "    #数据拼接\n",
    "    result_set = pd.concat([df,pd.DataFrame(clusterAssment)],axis=1,ignore_index=True)\n",
    "    #标志位\n",
    "    clusterChanged = True\n",
    "\n",
    "    while clusterChanged:\n",
    "        clusterChanged = False\n",
    "        for i in range(m):\n",
    "            dist = disMet(df.iloc[i,:n-1].values,centroids)\n",
    "            #当前距离最小值\n",
    "            result_set.iloc[i,-3] = dist.min()\n",
    "            #当前聚类结果 索引\n",
    "            result_set.iloc[i,-2] = np.where(dist == dist.min())[0]\n",
    "        # 所有点的分类全部不变，才能代表质心没有改变\n",
    "        clusterChanged = not(result_set.iloc[:,-1] == result_set.iloc[:,-2]).all()\n",
    "        \n",
    "        if clusterChanged:\n",
    "            #更新质心\n",
    "            cent_df = result_set.groupby(n+1).mean()\n",
    "            centroids = cent_df.iloc[:,:n-1].values\n",
    "            result_set.iloc[:,-1] = result_set.iloc[:,-2]\n",
    "\n",
    "    return centroids,result_set"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[6.85384615, 3.07692308, 5.71538462, 2.05384615],\n",
       "        [5.006     , 3.418     , 1.464     , 0.244     ],\n",
       "        [5.88360656, 2.74098361, 4.38852459, 1.43442623]]),\n",
       "        0    1    2    3               4         5    6    7\n",
       " 0    5.1  3.5  1.4  0.2     Iris-setosa  0.021592  1.0  1.0\n",
       " 1    4.9  3.0  1.4  0.2     Iris-setosa  0.191992  1.0  1.0\n",
       " 2    4.7  3.2  1.3  0.2     Iris-setosa  0.169992  1.0  1.0\n",
       " 3    4.6  3.1  1.5  0.2     Iris-setosa  0.269192  1.0  1.0\n",
       " 4    5.0  3.6  1.4  0.2     Iris-setosa  0.039192  1.0  1.0\n",
       " ..   ...  ...  ...  ...             ...       ...  ...  ...\n",
       " 145  6.7  3.0  5.2  2.3  Iris-virginica  0.355799  0.0  0.0\n",
       " 146  6.3  2.5  5.0  1.9  Iris-virginica  0.822118  2.0  2.0\n",
       " 147  6.5  3.0  5.2  2.0  Iris-virginica  0.399645  0.0  0.0\n",
       " 148  6.2  3.4  5.4  2.3  Iris-virginica  0.691953  0.0  0.0\n",
       " 149  5.9  3.0  5.1  1.8  Iris-virginica  0.707200  2.0  2.0\n",
       " \n",
       " [150 rows x 8 columns])"
      ]
     },
     "execution_count": 90,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "kmeans(iris,3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {},
   "outputs": [],
   "source": [
    "testSet = pd.read_table('testSet.txt',header=None)\n",
    "\n",
    "lable = pd.DataFrame(np.zeros(testSet.shape[0]))\n",
    "\n",
    "test_set = pd.concat([testSet,lable],axis=1,ignore_index=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {},
   "outputs": [],
   "source": [
    "test_cent,test_cluster = kmeans(test_set,4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[-2.46154315,  2.78737555],\n",
       "        [ 2.6265299 ,  3.10868015],\n",
       "        [ 2.65077367, -2.79019029],\n",
       "        [-3.53973889, -2.89384326]]),\n",
       "            0         1    2         3    4    5\n",
       " 0   1.658985  4.285136  0.0  2.320192  1.0  1.0\n",
       " 1  -3.453687  3.424321  0.0  1.390049  0.0  0.0\n",
       " 2   4.838138 -1.151539  0.0  7.469741  2.0  2.0\n",
       " 3  -5.379713 -3.362104  0.0  3.604773  3.0  3.0\n",
       " 4   0.972564  2.924086  0.0  2.769678  1.0  1.0\n",
       " ..       ...       ...  ...       ...  ...  ...\n",
       " 75 -2.793241 -2.149706  0.0  1.110999  3.0  3.0\n",
       " 76  2.884105  3.043438  0.0  0.070601  1.0  1.0\n",
       " 77 -2.967647  2.848696  0.0  0.259901  0.0  0.0\n",
       " 78  4.479332 -1.764772  0.0  4.395108  2.0  2.0\n",
       " 79 -4.905566 -2.911070  0.0  1.865780  3.0  3.0\n",
       " \n",
       " [80 rows x 6 columns])"
      ]
     },
     "execution_count": 93,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "test_cent,test_cluster"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.collections.PathCollection at 0xcb69d30>"
      ]
     },
     "execution_count": 96,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "#绘制原始数据集\n",
    "plt.scatter(test_cluster.iloc[:,0],test_cluster.iloc[:,1],c=test_cluster.iloc[:,-1])\n",
    "\n",
    "#绘制质心\n",
    "plt.scatter(test_cent[:,0],test_cent[:,1],color='red',marker='x',s=300)"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "8bfad08b73d8ae58273d7e252c9e1d922058e2a21d3a8ccb2a1b9808ae54a57f"
  },
  "kernelspec": {
   "display_name": "Python 3.8.0 32-bit",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.0"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
